package com.wang.just_read;

import com.wang.utils.DatabaseUtils;
import com.wang.utils.StateMachine;
import com.wang.utils.StringUtils;

import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

public class JustRead {
    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    private static class ExecuteContext {
        public String name;
        PreparedStatement statement;
        List<String> paramList;
    }

    private Map<String, ExecuteContext> map = new HashMap<>();

    public void register(String name, String sql) throws SQLException {
        // 解析sql
        // 状态机上下文
        // 0查找#，1找到#，直到找到}，回到0
        StringBuilder realSql = new StringBuilder();
        char[] chs = sql.toCharArray();
        int start = 0;
        int state = 0;
        List<String> param = new ArrayList<>();
        for (int i = 0; i < chs.length; i++) {
            //输入事件
            char ch = chs[i];
            if (state == 0) {
                // 状态转移方程
                if (ch != '#') continue;
                if ('{' != chs[i + 1]) throw new SQLException();
                state = 1;
                realSql.append(chs, start, i - start);
                realSql.append("?");
                i++;
                start = i + 1;
            } else if (state == 1) {
                // 状态转移方程
                if('}' != ch) continue;
                param.add(String.copyValueOf(chs, start, i - start));
                start = i + 1;
                state = 0;
            }
        }
        realSql.append(chs, start, chs.length - start);
        // 解析sql 结束
        ExecuteContext context = new ExecuteContext();
        context.statement = dataSource.getConnection().prepareStatement(realSql.toString());
        context.paramList = param;
        context.name = name;

        map.put(name, context);
    }

    public List<Map<String, Object>> execute(String name, Map<String, Object> data) throws SQLException {
        ExecuteContext context = map.get(name);
        PreparedStatement statement = context.statement;
        for (int i = 0; i < context.paramList.size(); i++) {
            String p = context.paramList.get(i);
            statement.setObject(i + 1, data.get(p));
        }
        ResultSet rs = statement.executeQuery();
        return DatabaseUtils.INSTANCE.map(rs);
    }

    public boolean contains(String name) {
        return map.get(name) != null;
    }

    public static void main(String[] args) throws SQLException {
        JustRead justRead = new JustRead();
        justRead.dataSource = DatabaseUtils.INSTANCE.dataSource();
        justRead.register("asd", "select * from user where id > #{id} limit 0, 1");
        Map<String, Object> map = new HashMap<>();
        map.put("id", 5);
        StringUtils.INSTANCE.printJson(justRead.execute("asd", map));
    }

}
